package com.nb.camerademo.single;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.util.Size;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * @author Administrator on 2024-05-24.
 * <p>
 * 站在顶峰 看世界
 * 落到谷底 思人生
 */
public class CameraSingle {

    private List<String> cameraIdList;
    private Context context;
    private CameraManager cameraManager;
    private int currentCameraIndex = 0;

    /**
     * 轮询时间
     */
    private long time = 10L * 60 * 1000;

    private static final String TAG = CameraSingle.class.getSimpleName();
    private volatile static CameraSingle instance = null;

    public static CameraSingle getInstance() {
        if (instance == null) {
            synchronized (CameraSingle.class) {
                if (instance == null) {
                    instance = new CameraSingle();
                }
            }
        }
        return instance;
    }

    public void initSDK(Context context) {
        this.context = context;
        startCamera();
    }

    private void startCamera() {
        cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        try {
            cameraIdList = Arrays.asList(cameraManager.getCameraIdList());
            Log.v(TAG, String.valueOf(cameraIdList.size()));
            if (cameraIdList.size() > 0) {
                CameraSingle.getInstance().openNextCamera();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void openNextCamera() {
//        if (currentCameraIndex == 0) {
//            currentCameraIndex = (currentCameraIndex + 1) % cameraIdList.size();
//            Log.v(TAG, String.valueOf(currentCameraIndex));
//            openNextCamera();
//            return;
//        }
        String cameraId = cameraIdList.get(currentCameraIndex);
        try {
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    // Start capturing images for the current camera device
                    startCapturing(camera);
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {
                    camera.close();
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    camera.close();
                }
            }, null);
        } catch (Exception e) {
            e.printStackTrace();
            handler.removeCallbacks(runnable);
            handler.postDelayed(runnable, time);
        }
    }

    private void startCapturing(CameraDevice camera) {
        CameraCharacteristics characteristics = null;
        try {
            characteristics = cameraManager.getCameraCharacteristics(cameraIdList.get(currentCameraIndex));
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        // 获取相机支持的输出格式和尺寸
        StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

        // 选择所需的图像分辨率
        Size[] sizes = map.getOutputSizes(ImageFormat.JPEG);
        Size imageSize = sizes[sizes.length - 1]; // 选择列表中的最后一个尺寸
        for (Size s :
                sizes) {
            Log.v(TAG, s.getWidth() + "*" + s.getHeight());
        }
        Toast.makeText(context, imageSize.getWidth() + "*" + imageSize.getHeight(), Toast.LENGTH_LONG).show();
        ImageReader imageReader = ImageReader.newInstance(imageSize.getWidth(), imageSize.getHeight(), ImageFormat.JPEG, 1);
        imageReader.setOnImageAvailableListener(reader -> {
            Image image = reader.acquireLatestImage();
            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);
            saveImage(bytes);
            image.close();
            // Increment current camera index and move to the next camera

            if (currentCameraIndex + 1 == cameraIdList.size()) {
                handler.removeCallbacks(runnable);
                handler.postDelayed(runnable, time);
            } else {
                currentCameraIndex = (currentCameraIndex + 1) % cameraIdList.size();
                Log.v(TAG, String.valueOf(currentCameraIndex));
                openNextCamera();
            }
        }, null);

        try {
            CaptureRequest.Builder captureBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureBuilder.set(CaptureRequest.JPEG_QUALITY, (byte) 100);
//            captureBuilder.set(CaptureRequest.JPEG_TARGET_SIZE, (byte) 100);
            captureBuilder.addTarget(imageReader.getSurface());

            camera.createCaptureSession(Collections.singletonList(imageReader.getSurface()),
                    new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession session) {
                            try {
                                session.capture(captureBuilder.build(), null, null);
                            } catch (Exception e) {
                                e.printStackTrace();
                                handler.removeCallbacks(runnable);
                                handler.postDelayed(runnable, time);
                            }
                        }

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                            // Handle configuration failure
                        }
                    }, null);
        } catch (Exception e) {
            e.printStackTrace();
            handler.removeCallbacks(runnable);
            handler.postDelayed(runnable, time);
        }
    }

    private void saveImage(byte[] bytes) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
        String fname = "IMG_" + sdf.format(new Date()) + ".jpg";
        Log.v(TAG, fname);
        File file = new File(context.getExternalFilesDir(null), fname);
        try (FileOutputStream output = new FileOutputStream(file)) {
            output.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Handler handler = new Handler(Looper.getMainLooper());
    private Runnable runnable = this::startCamera;
}
